#include "ckernel.h"

#define NetPackMap(a)   m_netPackMap[ a - _DEF_PACK_BASE]

//设置协议映射，根据收到包的类型去调用对应的函数
void Ckernel::setNetPackMap()
{
    memset(m_netPackMap,0,sizeof(m_netPackMap));
    NetPackMap(_DEF_PACK_LOGIN_RS)              = &Ckernel::slot_dealLoginRs;
    NetPackMap(_DEF_PACK_REGISTER_RS)         = &Ckernel::slot_dealRegisterRs;
    NetPackMap(_DEF_PACK_CREATEROOM_RS)   = &Ckernel::slot_dealCreateRoomRs;
    NetPackMap(_DEF_PACK_JOINROOM_RS)       = &Ckernel::slot_dealJoinRoomRs;
    NetPackMap(_DEF_PACK_ROOM_MEMBER)     = &Ckernel::slot_dealRoomMemberRs;
    NetPackMap(_DEF_PACK_LEAVEROOM_RQ )   = &Ckernel::slot_dealLeaveRq;
    NetPackMap(_DEF_PACK_AUDIO_FRAME )      = &Ckernel::slot_dealAudioFrameRq;
    NetPackMap(_DEF_PACK_VIDEO_FRAME )      = &Ckernel::slot_dealVideoFrameRq;
}

#include<QSettings>
#include<QApplication>
#include<QFileInfo>
//每次启动应用都会搞一个配置文件更新服务器的ip
void Ckernel::initConfig()
{
    m_serverIP = _DEF_SERVERIP;
    //路径设置  exe同级目录下创建一个config.ini
    //获取同级目录可以通过QApplication::applicationDirPath()获取
    QString path = QApplication::applicationDirPath() + "/config.ini";
    //判断是否存在
    QFileInfo info(path);
    QSettings settings(path,QSettings::IniFormat,NULL);//存在就打开，没有就创建
    if(info.exists() == true)
    {
        //加载配置文件 ip设置为配置文件中的ip
        //移动到net组
        settings.beginGroup("net");
        //读取，赋值
        QVariant ip = settings.value("ip");
        QString strip = ip.toString();
        //结束
        settings.endGroup();
        if(strip.isEmpty() == false)
        {
            m_serverIP = strip;
        }
    }
    else
    {
        //如果没有配置文件中的ip，写入默认的ip
        settings.beginGroup("net");
        settings.setValue("ip",m_serverIP);
        settings.endGroup();
    }
    qDebug()<<m_serverIP;
}

Ckernel::Ckernel(QObject *parent) : QObject(parent),m_id(0),m_roomid(0)
{
    //设置协议映射关系，并且配置文件
    setNetPackMap();
    initConfig();

    //添加网络（网络中介类）
    m_pClient = new TcpClientMediator;
    if(m_pClient->OpenNet( m_serverIP.toStdString().c_str() , _DEF_PORT ) == false)
    {
        qDebug()<<"open error";
        return;
    }
    //m_pClient网络中介类收到消息，发出信号，kernel类处理
    connect(m_pClient,SIGNAL(SIG_ReadyData(uint,char*,int)),
            this,SLOT(slot_dealData(uint,char*,int)));

    //添加音视频发送网络
    for(int i = 0;i<2;++i)
    {
        m_pAVclient[i] = new TcpClientMediator;
        m_pAVclient[i]->OpenNet(m_serverIP.toStdString().c_str(),_DEF_PORT);
        //这两个socket专门用来发送音频和视频
        connect(/*m_pClient*/m_pAVclient[i],SIGNAL(SIG_ReadyData(uint,char*,int)),
                this,SLOT(slot_dealData(uint,char*,int)));
    }

    //创建登录页面
    m_pLoginDlg = new LoginDialog;
    //这个登录页面收到一个登录信息就通知kernel处理登录信息
    connect(m_pLoginDlg,SIGNAL(SIG_loginCommit(QString,QString)),
            this,SLOT(slot_loginCommit(QString,QString)));

    //登录页面关闭，发送信号给kernel，退出程序
    connect(m_pLoginDlg,SIGNAL(SIG_close()),
            this,SLOT(slot_destroy()));//关闭登录页面
    connect(m_pLoginDlg,SIGNAL(SIG_registerCommit(QString,QString,QString)),
            this,SLOT(slot_registerCommit(QString,QString,QString)));

    //创建会议页面
    m_pHuiyiDlg = new huiyiDialog;
    connect(m_pHuiyiDlg,SIGNAL(SIG_createRoom()),
            this,SLOT(slot_createRoom()));
    connect(m_pHuiyiDlg,SIGNAL(SIG_joinRoom()),
            this,SLOT(slot_joinRoom()));
    connect(m_pHuiyiDlg,SIGNAL(SIG_close()),
            this,SLOT(slot_destroy()));//关闭主页面

    //创建房间页面
    m_pRoomDlg = new roomDialog;
    connect(m_pRoomDlg,SIGNAL(SIG_close()),
            this,SLOT(slot_quitroom()));
    //connect(m_pRoomDlg,SIGNAL(SIG_createRoom()),
            //this,SLOT(slot_createRoom()));

    //创建音频录入
    m_pAudioRead = new AudioRead;
    connect(m_pAudioRead,SIGNAL(SIG_audioFrame(QByteArray)),
            this,SLOT(slot_audioFrame(QByteArray)));
    connect(m_pRoomDlg,SIGNAL(SIG_audioStart()),
            this,SLOT(slot_audioStart()));
    connect(m_pRoomDlg,SIGNAL(SIG_audioPause()),
            this,SLOT(slot_audioPause()));

    //创建视频录入
    m_pVideoRead = new videoRead;
    connect(m_pVideoRead,SIGNAL(SIG_sendVideoFrame(QImage)),
            this,SLOT(slot_sendVideoFrame(QImage)));
    connect(m_pRoomDlg,SIGNAL(SIG_videoStart()),
            this,SLOT(slot_videoStart()));
    connect(m_pRoomDlg,SIGNAL(SIG_videoPause()),
            this,SLOT(slot_videoPause()));

    //房间页面发送设置滤镜信号，videoread类调用设置滤镜函数
    connect(m_pRoomDlg,SIGNAL(SIG_setMoji(int)),
            m_pVideoRead,SLOT(slot_setMoji(int)));

    //创建桌面录入
    m_pScreenRead = new ScreenRead;
    connect(m_pScreenRead,SIGNAL(SIG_getScreenFrame(QImage)),
            this,SLOT(slot_sendVideoFrame(QImage)));
    connect(m_pRoomDlg,SIGNAL(SIG_screenStart()),
            this,SLOT(slot_screenStart()));
    connect(m_pRoomDlg,SIGNAL(SIG_screenPause()),
            this,SLOT(slot_screenPause()));

    //创建多线程发送音频类
    m_pSendAudioWorker = QSharedPointer<CsendAudioWorker>(new CsendAudioWorker);
    connect(this,SIGNAL(SIG_sendAudio(char*,int)),
            m_pSendAudioWorker.data(),SLOT(slot_sendAudio(char*,int)));

    //创建多线程发送视频类
    m_pSendVideoWorker = QSharedPointer<CsendVideoWorker>(new CsendVideoWorker);
    connect(this,SIGNAL(SIG_sendVideo(char *buf, int nlen)),
            m_pSendVideoWorker.data(),SLOT(slot_sendVideo(char *buf, int nlen)));

    m_pLoginDlg->show();
}

//kernel回收，程序结束
void Ckernel::slot_destroy()
{
    if(m_pHuiyiDlg != nullptr)//删除会议窗体
    {
        delete m_pHuiyiDlg;
        m_pHuiyiDlg = nullptr;
    }
    if(m_pLoginDlg != nullptr)//删除登录窗体
    {
        delete m_pLoginDlg;
        m_pLoginDlg = nullptr;
    }
    if(m_pAudioRead != nullptr)//删除音频读入窗体
    {
        m_pAudioRead->pause();
        delete m_pAudioRead;
        m_pAudioRead = nullptr;
    }
    if(m_pVideoRead != nullptr)//删除视频读入窗体
    {
        m_pVideoRead->slot_closeVideo();
        delete m_pVideoRead;
        m_pVideoRead = nullptr;
    }
    if(m_pScreenRead != nullptr)//删除桌面读入窗体
    {
        m_pScreenRead->slot_closeVideoScreen();
        delete m_pScreenRead;
        m_pScreenRead = nullptr;
    }
    if(m_pRoomDlg != nullptr)//删除房间窗体
    {
        m_pRoomDlg->hide();
        delete m_pRoomDlg;
        m_pRoomDlg = nullptr;
    }
    if(m_pClient != nullptr)//删除网络控件
    {
        m_pClient->CloseNet();
        delete m_pClient;
        m_pClient = nullptr;
    }
    exit(0);
}

//网络处理
void Ckernel::slot_dealData(uint sock, char *buf, int nlen)
{
    int type = *(int*)buf;//前4字节是协议头
    if(type >= _DEF_PACK_BASE && type<_DEF_PACK_BASE + _DEF_PACK_COUNT)
    {
        //取得协议头，根据协议映射关系找到函数指针，通过函数指针调用函数处理
        PFUN pf = NetPackMap(type);
        qDebug() << __func__ <<" pf";
        if(pf != NULL)
        {
            (this->*pf)(sock,buf,nlen);
        }
    }
    delete[] buf;
}

#define MD5_KEY (1234)
//获得一个md5值
static std::string getMD5(QString value)
{
    QString str = QString("%1_%2").arg(value).arg(1234);
    std::string strSrc = str.toStdString();
    MD5 md5(strSrc);
    return md5.toString();
}

//发送登录信息
void Ckernel::slot_loginCommit(QString tel, QString pass)
{
    std::string strTel = tel.toStdString();
    std::string strPassMD5 = getMD5(pass);
    STRU_LOGIN_RQ rq;
    strcpy(rq.m_tel , strTel.c_str());
    strcpy(rq.m_password , strPassMD5.c_str());

    m_pClient->SendData(0,(char*)&rq,sizeof(rq));
}

//发送注册信息
void Ckernel::slot_registerCommit(QString tel, QString pass, QString name)
{
    std::string strTel = tel.toStdString();
    std::string strPassMD5 = getMD5(pass);
    std::string strName = name.toStdString();//格式为utf8
    STRU_REGISTER_RQ rq;
    strcpy(rq.m_tel , strTel.c_str());
    strcpy(rq.m_password , strPassMD5.c_str());
    strcpy(rq.m_name , strName.c_str());

    m_pClient->SendData(0,(char*)&rq,sizeof(rq));
}

//登录回复
void Ckernel::slot_dealLoginRs(uint sock, char *buf, int nlen)
{
    qDebug()<<__func__;
    //拆包
    STRU_LOGIN_RS* rs = (STRU_LOGIN_RS*)buf;
    //根据返回结果得到不同的信息
    switch (rs->m_result)
    {
    case user_not_exist:
        QMessageBox::about(m_pLoginDlg,"提示","用户不存在，登录失败");
        break;
    case password_error:
        QMessageBox::about(m_pLoginDlg,"提示","密码错误，登录失败");
        break;
    case login_success:
    {
        QString strName = QString("用户[%1]登陆成功").arg(rs->m_name);
        QMessageBox::about(m_pLoginDlg,"提示",strName);
        //id记录
        m_id = rs->m_userid;
        m_name = QString::fromStdString(rs->m_name);
        m_pHuiyiDlg->setInfo(m_name,0);
        //ui跳转
        m_pLoginDlg->hide();
        m_pHuiyiDlg->showNormal();
        //注册视频和音频的fd
        STRU_AUDIO_REG rq_audio;
        rq_audio.m_userid = m_id;
        STRU_VIDEO_REG rq_video;
        rq_video.m_userid = m_id;
        m_pAVclient[audio_client]->SendData(0,(char*)&rq_audio,sizeof(rq_audio));
        m_pAVclient[video_client]->SendData(0,(char*)&rq_video,sizeof(rq_video));
        break;
    }
    default:
        break;
    }
}

//注册回复
void Ckernel::slot_dealRegisterRs(uint sock, char *buf, int nlen)
{
    qDebug()<<__func__;
    //拆包，根据不同结果弹出不同的提示窗
    STRU_REGISTER_RS* rs = (STRU_REGISTER_RS*)buf;
    switch (rs->m_result) {
    case tel_is_exist:
        QMessageBox::about(m_pLoginDlg,"提示","手机号已存在，注册失败");
        break;
    case register_success:
        QMessageBox::about(m_pLoginDlg,"提示","成功");
        break;
    case name_is_exist:
        QMessageBox::about(m_pLoginDlg,"提示","昵称已存在，注册失败");
        break;
    default:
        break;
    }
}

#include<QInputDialog>
#include<QRegExp>
//创建房间
void Ckernel::slot_createRoom()
{
    //判断是否在房间内，m_roomid
    if(m_roomid != 0)
    {
        QMessageBox::about(m_pHuiyiDlg,"提示","已经在房间内了");
        return;
    }
    //发命令，创建房间
    STRU_CREATEROOM_RQ rq;
    rq.m_userid = m_id;
    m_pClient->SendData(0,(char*)&rq,sizeof(rq));

    //音频初始化
    m_pRoomDlg->slot_setAudioCheck(false);
    //视频初始化
    m_pRoomDlg->slot_setVideoCheck(false);
    //桌面采集初始化
    m_pRoomDlg->slot_setScreenCheck(false);
}

#include<QInputDialog>
//加入房间
void Ckernel::slot_joinRoom()
{
    //判断是否在房间内，m_roomid
    if(m_roomid != 0)
    {
        QMessageBox::about(m_pHuiyiDlg,"提示","已经在房间内了");
        return;
    }
    //弹出窗口，填房间号
    QString strRoom = QInputDialog::getText(m_pHuiyiDlg,"加入房间","请输入房间号");
    QRegExp exp("^[0-9]\{1,8\}$");
    if(exp.exactMatch(strRoom) == false)
    {
        QMessageBox::about(m_pHuiyiDlg,"提示","房间号输入不合法，应为8位数字");
        return;
    }
    qDebug()<<strRoom;
    //发命令，加入房间
    STRU_JOINROOM_RQ rq;
    rq.m_userid = m_id;
    rq.m_roomid = strRoom.toInt();
    m_pClient->SendData(0,(char*)&rq,sizeof(rq));
    //音频初始化
    m_pRoomDlg->slot_setAudioCheck(false);
    //视频初始化
    m_pRoomDlg->slot_setVideoCheck(false);
    //桌面采集初始化
    m_pRoomDlg->slot_setScreenCheck(false);
}

//创建房间回复处理
void Ckernel::slot_dealCreateRoomRs(uint sock, char *buf, int nlen)
{
    qDebug()<<__func__;
    STRU_CREATEROOM_RS* rs = (STRU_CREATEROOM_RS*)buf;
    //房间号显示到页面，跳转
    m_roomid = rs->m_roomid;
    m_pRoomDlg->slot_setInfo(QString::number(m_roomid));

    //服务器没有把个人信息发给自己的话，作为第一个进入房间的人：
    //把自己的信息放到房间里
    userShow* user = new userShow;
    connect(user,SIGNAL(SIG_itemClicked(int,QString)),
            m_pRoomDlg,SLOT(slot_setBigImgID(int,QString)));
    user->slot_setInfo(m_id,m_name);
    m_pRoomDlg->slot_addUserShow(user);


    m_pRoomDlg->showNormal();
}

//加入房间回复处理
void Ckernel::slot_dealJoinRoomRs(uint sock, char *buf, int nlen)
{
    qDebug()<<__func__;
    STRU_JOINROOM_RS* rs = (STRU_JOINROOM_RS*)buf;
    //根据不同结果显示失败或者进入房间跳转
    if(rs->m_result == 0)
    {
        QMessageBox::about(m_pHuiyiDlg,"提示" , "房间id不存在，加入失败");
        return;
    }
    //设置roomid,显示会议页面
    m_roomid = rs->m_roomid;
    m_pRoomDlg->slot_setInfo(QString::number(m_roomid));
    //把自己的信息放到房间里
    userShow* user = new userShow;
    connect(user,SIGNAL(SIG_itemClicked(int,QString)),
            m_pRoomDlg,SLOT(slot_setBigImgID(int,QString)));
    user->slot_setInfo(m_id,m_name);
    m_pRoomDlg->slot_addUserShow(user);

    m_pRoomDlg->showNormal();
}

//加入成员处理
void Ckernel::slot_dealRoomMemberRs(uint sock, char *buf, int nlen)
{
    STRU_ROOM_MEMBER_RQ* rq = (STRU_ROOM_MEMBER_RQ*)buf;
    //rq->m_userid;
    //rq->szUserName;
    qDebug()<<"加入成员id:"<<rq->m_userid<<";加入成员昵称:"<<rq->szUserName;

    userShow* user = new userShow;//给这个新加入的成员新建一个窗口
    //这个窗口发送一个信号：它被单击作为会议主显示页面
    //房间页面对象槽函数：设置房间主显示页面的id和名字
    connect(user,SIGNAL(SIG_itemClicked(int,QString)),
            m_pRoomDlg,SLOT(slot_setBigImgID(int,QString)));
    user->slot_setInfo(rq->m_userid,QString::fromStdString(rq->szUserName));
    m_pRoomDlg->slot_addUserShow(user);

    //音频的内容
    AudioWrite* aw = nullptr;
    //为每个人创建一个播放音频的对象
    if(m_mapIdToAudioWrite.count(rq->m_userid) == 0)
    {
        aw = new AudioWrite;
        m_mapIdToAudioWrite[rq->m_userid] = aw;
    }
    //视频的内容
    //VideoWriter * vw = nullptr;
}

//自己要退出房间
void Ckernel::slot_quitroom()
{
    m_roomid = 0;
    //发退出包
    STRU_LEAVEROOM_RQ rq;
    rq.m_userid = m_id;
    rq.m_roomid = m_roomid;
    strcpy(rq.szUserName,m_name.toStdString().c_str());

    m_pClient->SendData(0,(char*)&rq,sizeof(rq));
    //关闭音频，视频，桌面采集
    m_pAudioRead->pause();
    m_pRoomDlg->slot_setAudioCheck(false);
    m_pVideoRead->slot_closeVideo();
    m_pRoomDlg->slot_setVideoCheck(false);
    m_pScreenRead->slot_closeVideoScreen();
    m_pRoomDlg->slot_setScreenCheck(false);
    //回收所有人的audiowrite
    for(auto it = m_mapIdToAudioWrite.begin();it != m_mapIdToAudioWrite.end();)
    {
        AudioWrite* pw = it->second;
        it = m_mapIdToAudioWrite.erase(it);
        delete pw;
    }
    //回收资源
    m_pRoomDlg->slot_clearUserShow();
}

//有人要退出房间
void Ckernel::slot_dealLeaveRq(uint sock, char *buf, int nlen)
{
    //拆包
    STRU_LEAVEROOM_RQ* rq = (STRU_LEAVEROOM_RQ*)buf;
    //把这个人从ui上去掉
    if(rq->m_roomid == m_roomid)
    {
        m_pRoomDlg->slot_removeUserShow(rq->m_userid);
    }

    //删除这个人的声音播放
    if(m_mapIdToAudioWrite.count( rq->m_userid )> 0)
    {
        AudioWrite* paw = m_mapIdToAudioWrite[rq->m_userid];
        m_mapIdToAudioWrite.erase(rq->m_userid);
        delete paw;
    }
}

//暂停音频
void Ckernel::slot_audioPause()
{
    m_pAudioRead->pause();
}

//开始音频
void Ckernel::slot_audioStart()
{
    m_pAudioRead->start();
}

//发送音频帧
void Ckernel::slot_audioFrame(QByteArray ba)
{
    int nPackSize = 6*sizeof(int) + ba.size();
    char* buf = new char[nPackSize];
    char* tmp = buf;
    //序列化
    int type = _DEF_PACK_AUDIO_FRAME;
    int userid = m_id;
    int roomid = m_roomid;
    QTime tm = QTime::currentTime();
    int min = tm.minute();
    int sec = tm.second();
    int msec = tm.msec();

    *(int*)tmp = type;
    tmp += sizeof(int);
    *(int*)tmp = userid;
    tmp += sizeof(int);
    *(int*)tmp = roomid;
    tmp += sizeof(int);
    *(int*)tmp = min;
    tmp += sizeof(int);
    *(int*)tmp = sec;
    tmp += sizeof(int);
    *(int*)tmp = msec;
    tmp += sizeof(int);

    memcpy(tmp,ba.data(),ba.size());

    //把音视频发送变成一个信号，放到另一个线程去执行。
//    m_pAVclient[audio_client]->SendData(0,buf,nlen);
//    delete []buf;
    Q_EMIT SIG_sendAudio(buf,nPackSize);
}

//暂停视频
void Ckernel::slot_videoPause()
{
    m_pVideoRead->slot_closeVideo();
}

//开始视频
void Ckernel::slot_videoStart()
{
    m_pVideoRead->slot_openVideo();
}

//刷新房间页面主usershow窗口
void Ckernel::slot_refreshVideo(int id,QImage& img)
{
    m_pRoomDlg->slot_refreshUser(id,img);
}

//暂停桌面采集
void Ckernel::slot_screenPause()
{
    m_pScreenRead->slot_closeVideoScreen();
}

//开启桌面采集
void Ckernel::slot_screenStart()
{
    m_pScreenRead->slot_openVideoScreen();
}

//音频帧的处理->播放音频
void Ckernel::slot_dealAudioFrameRq(uint sock, char *buf, int nlen)
{
    //拆包
    char* tmp = buf;
    //反序列化
    //QTime tm = QTime::currentTime();
    //int min = tm.minute();
    //int sec = tm.second();
    //int msec = tm.msec();

    //*(int*)tmp = type;
    tmp += sizeof(int);
    int userid = *(int*)tmp;
    tmp += sizeof(int);
    int roomid = *(int*)tmp;
    tmp += sizeof(int);
    //*(int*)tmp = min;
    tmp += sizeof(int);
    //*(int*)tmp = sec;
    tmp += sizeof(int);
    //*(int*)tmp = msec;
    tmp += sizeof(int);

    int nbuflen = nlen-6*sizeof(int);
    QByteArray ba(tmp,nbuflen);

    if(m_roomid == roomid)
    {
        if(m_mapIdToAudioWrite.count(userid) > 0)
        {
            AudioWrite* aw = m_mapIdToAudioWrite[userid];
            aw->slot_playAudio(ba);
        }
    }

    delete[] buf;
}

//视频帧的处理->播放视频
void Ckernel::slot_dealVideoFrameRq(uint sock, char *buf, int nlen)
{
    char* tmp = buf;
    tmp += sizeof(int);//跳过包类型
    int userid = *(int*)tmp;
    tmp += sizeof(int);
    int roomid = *(int*)tmp;
    tmp += sizeof(int);

    tmp += sizeof(int);tmp += sizeof(int);tmp += sizeof(int);//跳过时间

    int datalen = nlen - 6*sizeof(int);
    QByteArray ba(tmp,datalen);
    QImage img;
    img.loadFromData(ba);
    if(m_roomid == roomid)
    {
        m_pRoomDlg->slot_refreshUser(userid,img);
    }

    delete[] buf;
}

#include <QBuffer>
//发送视频帧
void Ckernel::slot_sendVideoFrame(QImage img)
{
    //显示图片
    slot_refreshVideo(m_id,img);
    //压缩图片从 RGB24 格式压缩到 JPEG 格式, 发送出去
    QByteArray ba;
    QBuffer qbuf(&ba); // QBuffer 与 QByteArray 字节数组联立联系
    img.save( &qbuf , "JPEG" , 50 ); //将图片的数据写入 ba
    //使用 ba 对象, 可以获取图片对应的缓冲区
    //可以使用 ba.data() , ba.size()将缓冲区发送出去

    //写视频帧并发送
    //视频数据帧
    //成员描述
    //int type;
    //int userid;
    //int roomid;
    //int min;
    //int sec;
    //int msec;
    //QByteArray videoFrame
    int npackSize = 6*sizeof(int) + ba.size();
    char* buf = new char[npackSize];
    char* tmp = buf;

    *(int*)tmp = _DEF_PACK_VIDEO_FRAME;
    tmp += sizeof(int);
    *(int*)tmp = m_id;
    tmp += sizeof(int);
    *(int*)tmp = m_roomid;
    tmp += sizeof(int);

    //出现延迟过长的情况舍弃一些帧，参考这个时间
    QTime time = QTime::currentTime();
    *(int*)tmp = time.minute();
    tmp += sizeof(int);
    *(int*)tmp = time.second();
    tmp += sizeof(int);
    *(int*)tmp = time.msec();
    tmp += sizeof(int);

    memcpy(tmp,ba.data(),ba.size());

    //m_pAVclient[video_client]->SendData(0,buf,npackSize);
    Q_EMIT SIG_sendVideo(buf,npackSize);
}

//多线程发送音频
void Ckernel::slot_SendAudio(char *buf, int nlen)
{
    char* tmp = buf;
    tmp += sizeof(int);
    tmp += sizeof(int);
    tmp += sizeof(int);

    int min = *(int*)tmp;
    tmp += sizeof(int);
    int sec = *(int*)tmp;
    tmp += sizeof(int);
    int msec = *(int*)tmp;
    tmp += sizeof(int);

    //当前时间
    QTime ctm = QTime::currentTime();
    //数据包的时间
    QTime tm(ctm.hour(),min,sec,msec);
    //如果发送数据包延迟超过300ms舍弃
    if(tm.msecsTo(ctm) > 300)
    {
        qDebug()<<"send音频 舍弃超时";
        delete []buf;
        return;
    }

    m_pAVclient[audio_client]->SendData(0,buf,nlen);
    delete[] buf;
}

//多线程发送视频
void Ckernel::slot_SendVideo(char *buf, int nlen)
{
    char* tmp = buf;
    tmp += sizeof(int);
    tmp += sizeof(int);
    tmp += sizeof(int);

    int min = *(int*)tmp;
    tmp += sizeof(int);
    int sec = *(int*)tmp;
    tmp += sizeof(int);
    int msec = *(int*)tmp;
    tmp += sizeof(int);

    //当前时间
    QTime ctm = QTime::currentTime();
    //数据包的时间
    QTime tm(ctm.hour(),min,sec,msec);
    //如果发送数据包延迟超过300ms舍弃
    if(tm.msecsTo(ctm) > 300)
    {
        qDebug()<<"send视频 舍弃超时";
        delete []buf;
        return;
    }

    m_pAVclient[video_client]->SendData(0,buf,nlen);
    delete[] buf;
}





